有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java泛型在实现接口的类上指定上界,接口本身指定上界

我有以下界面:

public interface ISort<T extends Comparable<T>> {
    public void sort(T[] array);
}

我的理解是,<T extends Comparable<T>>告诉编译器,在这个类中,可能有一些泛型类型T,它们必须是Comparable<T>或是实现Comparable<T>的任何类

然后我有以下课程:

public class Sort<T extends Comparable<T>> implements ISort<T> {

    public void swap(T[] array, int i, int j) {
        T temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }

    public void sort(T[] array) {
        java.util.Arrays.sort(array);
    }

}

同样,我让<T extends Comparable<T>>告诉编译器,在这个类中,我将使用类型T,它必须与Comparable<T>形成IS-A关系。但是,为什么我必须只键入implements ISort<T>,为什么我不需要写入implements ISort<T extends Comparable<T>>?为了帮助我理解这一点,您能解释一下这些泛型语句对编译器的确切推断吗


共 (3) 个答案

  1. # 1 楼答案

    在类声明中,引入一个具有上限的类型参数。当您使用T[]作为sort方法的第一个参数的类型时,您不是声明任何内容(声明发生在文件的开头):您只是使用类型变量。请注意不同的措辞:

    • 在文件的开头,您声明了一个类型参数
    • 在sort的签名中,我们使用类型变量

    类型参数的边界仅允许在声明站点上进行,声明可以在三个位置进行:

    1. 类声明
    2. 构造函数定义
    3. 方法定义

    这是一张快捷的桌子:

    // class
    public static class Foo<T> {
        // constructor
        public <A> Foo() {}
        // method
        public <B> void doSomething() {}
        // Not really allowed
        // public void doSomethingElse(List<T extends Number> bar) {}
        // here we have a wildcard, so you can do this
        public void doSomethingElse(List<? super T> bar) {}
    }
    
  2. # 2 楼答案

    使用类指定T与在extends或implements子句中使用T之间存在差异

    在类中指定T时,您是声明类型参数T,但在extends或implements子句中,您是使用已声明的类型参数

    public class Sort<T extends Comparable<T>>  // Declare T to be Comparable<T>
        implements ISort<T>                     // Use T
    

    在extends或implements子句中使用类型参数与在类的主体中使用类型参数没有什么不同

  3. # 3 楼答案

    泛型类型用法的语法是SomeType<SomeTypeArgument>

    就你而言

    class Sort<T extends Comparable<T>> implements ISort<T> {
            // ^ declares new type parameter             ^ uses it as a type argument 
            //                             
    

    声明一个新的类型参数T,其边界与ISort中声明的类型参数T中的期望值相匹配。因此,您可以使用Sort#T作为ISort的类型参数

    这将类似于

    class Sort implements ISort<Integer> {
    

    唯一的区别是您不声明类型参数,而是使用现有类型